
package cn.zniot.so.transport.server;

import cn.zniot.so.apiprovide.business.DownloadFileHandler;
import cn.zniot.so.apiprovide.business.ForgetSecretHandler;
import cn.zniot.so.apiprovide.business.LoginHandler;
import cn.zniot.so.apiprovide.business.UserRegisterHandler;

import org.apache.mina.core.session.IoSession;
import org.apache.mina.handler.stream.StreamIoHandler;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

public class HttpProtocolHandler extends StreamIoHandler {

    @Override
    protected void processStreamIo(IoSession session, InputStream in,
            OutputStream out) {

        String url;
        BufferedReader inB = new BufferedReader(new InputStreamReader(in));
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(out));
        PrintWriter outPW = new PrintWriter(bufferedWriter);

        // to read http post
        try {
            String firstLines = inB.readLine();
            String[] tmps = firstLines.split(" ");
            // --------------------------------------------------只处理POST请求
            int contentLenAAA = -1;
            if (tmps != null && "POST".equalsIgnoreCase(tmps[0].trim())) {

                while (true)
                {
                    // 1.read header first unti
                    // 1 .Read http headers
                    String headerLineString = inB.readLine();
                    if (headerLineString != null && headerLineString.trim().length() == 0)
                    {

                        if (contentLenAAA == -1)
                        {
                            // no content length got //error !!!!!
                            break;
                        }
                        else
                        {
                            byte[] content = new byte[contentLenAAA];
                            int debugA = in.read(content);
                            String testContentString = null;
                            if (debugA == -1)
                            {
                                testContentString = inB.readLine();
                            } else {
                                testContentString = new String(content, "UTF-8");
                            }
                            // String cccString = new
                            // String(content,"ISO-8859-1");
                            // String dddString = new
                            // String(cccString.getBytes("UTF-8"),
                            // "ISO-8859-1");
                            // String contents = new
                            // String(bbbString.getBytes("UTF-8"),
                            // "ISO-8859-1");
                            // System.out.println(bbbString);
                            String result;
                            try
                            {

                                Map<String, String> paramsPost = new HashMap<String, String>();
                                String[] paraList = testContentString.split("&");
                                for (String str : paraList)
                                {
                                    paramsPost.put(str.split("=")[0], str
                                            .split("=").length > 1 ? str
                                            .split("=")[1] : null);
                                }
                                UserRegisterHandler userRegisterHandler = null;
                                if (userRegisterHandler == null) {
                                    userRegisterHandler = new UserRegisterHandler();
                                }
                                result = userRegisterHandler.handle(paramsPost);
                            } catch (RuntimeException e)
                            {
                                outPW.println("HTTP/1.1 404 Not Found");
                                outPW.println("Content-Type: text/xml");
                                outPW.println();
                                return;
                            }
                            // Write header
                            outPW.println("HTTP/1.1 200 OK");
                            outPW.println("Content-Type: application/x-json;charset=UTF-8");
                            outPW.println("Charset: UTF-8");
                            outPW.println("Content-Length: "
                                    + result.getBytes("UTF-8").length);
                            outPW.println();
                            outPW.println(result);
                            return;
                        }
                    }
                    String[] tmpHeader = headerLineString.split(":");
                    if (tmpHeader != null
                            && tmpHeader[0].trim().equalsIgnoreCase("Content-Length"))
                    {
                        contentLenAAA = Integer.parseInt(tmpHeader[1].trim());
                    }
                }
            }

            // Get request URL.
            // ------------------------------------------只处理GET请求
            url = tmps[1];
            String result = null;
            // 我这里只做简单的截取处理，一般还要包括编码解析，特殊字符处理，如&,=之类的
            Map<String, String> params = new HashMap<String, String>();
            try
            {
                String paraStrs = tmps[1].split("\\?")[1];
                String[] paraList = paraStrs.split("&");
                for (String str : paraList)
                {
                    params.put(str.split("=")[0],
                            str.split("=").length > 1 ? str.split("=")[1]
                                    : null);
                }
            } catch (Exception e1)
            {
                // http get请求格式错误
                return;
            }

            // 这段程序，可以读HTTP请求的头信息，主要用于安全验证，可不管 // Read header
            // Map<String, String> headers = new TreeMap<String, String>();
            // String line;
            // while ((line = inB.readLine()) != null && !line.equals(""))
            // {
            // String[] tokens = line.split(": ");
            // headers.put(tokens[0], tokens[1]);
            // }

            String stream = url.substring(1, 19);
            if (stream.equals("mobileZniot/login?")) {// 这里加上全部的，写成相等也行
                LoginHandler handler = null;
                if (handler == null) {
                    handler = new LoginHandler();
                }
                result = handler.handle(params);
            } else if (stream.equals("mobileZniot/forget")) {
                ForgetSecretHandler operateHandler = null;
                if (operateHandler == null) {
                    operateHandler = new ForgetSecretHandler();
                }
                result = operateHandler.handle(params);
            } else if (stream.equals("mobileZniot/loadcf")) {
                DownloadFileHandler downloadFileHandler = null;
                if (downloadFileHandler == null) {
                    downloadFileHandler = new DownloadFileHandler();
                }
                result = downloadFileHandler.handle(params);
            } else {
                // 完成回应消息
                outPW.println("HTTP/1.0 404 Not Found");
                outPW.println("Content-Type: text/xml");
                outPW.println();
                return;
            }
            // Write header
            outPW.println("HTTP/1.0 200 OK");
            outPW.println("Content-Type: application/x-json;charset=UTF-8");
            outPW.println();
            outPW.println(result);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        } finally
        {
            if (in != null)
            {
                outPW.flush();
            }
            outPW.close();
            try
            {
                in.close();
                inB.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }

    }

    /*
     * @覆盖父类或实现接口的messageReceived（IoSession session, Object buf）方法
     * 方法名：messageReceived(IoSession session, Object buf) 功 能：& 错误发送
     * 发送字符串：123(十六进制为31 32 33)这种发送无法触发messageReceived 正确发送 在原有十六进制末尾上加0D
     * 0A(换行符) ，变为31 32 33 0D 0A 即可触发messageReceived！ 参 数：IoSession session,
     * Object buf -&收到的请求 返回值：&返回值类型 - &返回值为空 参 考：@see
     * org.apache.mina.handler.stream
     * .StreamIoHandler#messageReceived(org.apache.mina.core.session.IoSession,
     * java.lang.Object)
     */
    @Override
    public void messageReceived(IoSession session, Object buf)
    {
        super.messageReceived(session, buf);
    }

    @Override
    public void sessionClosed(IoSession session) throws Exception
    {
        super.sessionClosed(session);
    }

    @Override
    public void exceptionCaught(IoSession session, Throwable cause)
    {
        // super.exceptionCaught(session, cause);
        if (session == null)
        {
            return;
        }
    }

    public static byte[] convertstream(InputStream inStream, long length) throws IOException {
        length = length > Integer.MAX_VALUE ? Integer.MAX_VALUE : length;
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream((int) length);
        byte[] buff = new byte[10240];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 10240)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] buf = swapStream.toByteArray();
        swapStream.close();
        return buf;
    }

    /**
     * 以字节为单位读取文件，常用于读二进制文件，如图片、声音、影像等文件。
     */
    public static void readFileByBytes(String fileName)
    {
        InputStream in = null;
        try
        {
            System.out.println("以字节为单位读取文件内容，一次读多个字节：");
            // 一次读多个字节
            in = new FileInputStream(fileName);
            convertstream(in, in.available());
        } catch (Exception e1)
        {
            e1.printStackTrace();
        } finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                } catch (IOException e1)
                {
                }
            }
        }

    }
}
